#include <mips/regdef.h>
#include <sys/syscall.h>
#define stdinfd 	0
#define stdoutfd 	1



#define LOAD_DATA_SS 48
#define LOAD_DATA_O_ARG (LOAD_DATA_SS)
#define LOAD_DATA_O_RA 40
#define LOAD_DATA_O_FP 36
#define LOAD_DATA_O_GP 32
#define LOAD_DATA_LTA_BYTES_TOTALES	28
#define LOAD_DATA_LTA_NUM_BUFFERS	24
#define LOAD_DATA_LTA_OFFSET		20
#define LOAD_DATA_LTA_BUFFER		16
#define TAM_BUFFER 1024
.text
.align 	2
.globl	load_data
.ent	load_data
load_data:
	.frame $fp, LOAD_DATA_SS, ra
	.set  noreorder
   	.cpload  t9
   	.set  reorder

	subu	sp, sp, LOAD_DATA_SS
	sw	ra, LOAD_DATA_O_RA(sp)
	sw	$fp, LOAD_DATA_O_FP(sp)
	sw	gp, LOAD_DATA_O_GP(sp)
	move	$fp, sp
	sw	a0, LOAD_DATA_O_ARG(sp)	# guardo el argumento en el ABA del caller

	# inicializo todas las variables a 0
	sw	zero,LOAD_DATA_LTA_BYTES_TOTALES(sp)
	sw	zero,LOAD_DATA_LTA_OFFSET(sp)	
	sw	zero,LOAD_DATA_LTA_BUFFER(sp)

	# creo un buffer de tamanio TAM_BUFFER
	li	a0, TAM_BUFFER

	la	t9, mymalloc
	jalr	t9
	beqz	v0, return_load_data
	sw	v0, LOAD_DATA_LTA_BUFFER(sp)
	li	t0, 1
	sw	t0, LOAD_DATA_LTA_NUM_BUFFERS(sp)
loop:
	# leo de stdin
	li	a0, stdinfd
	lw	t0, LOAD_DATA_LTA_OFFSET(sp)
	lw	t1, LOAD_DATA_LTA_BUFFER(sp)
	addu	a1, t0, t1
	li	a2, TAM_BUFFER
	la	t9, my_read
	jalr 	t9
	bltz	v0, error
	# actualizo los bytes leidos
	lw	t2, LOAD_DATA_LTA_BYTES_TOTALES(sp)
	addu	t2, v0, t2
	sw	t2,LOAD_DATA_LTA_BYTES_TOTALES(sp)

	bltu	v0, TAM_BUFFER, return_load_data

	# actualizo el numero de buffers
	lw	t3, LOAD_DATA_LTA_NUM_BUFFERS(sp)
	addiu	t3, 1
	sw	t3, LOAD_DATA_LTA_NUM_BUFFERS(sp)

	# llamo a realloc para agrandar el buffer
	lw	a0, LOAD_DATA_LTA_BUFFER(sp)
	mul	a1, t3, TAM_BUFFER
	la	t9, myrealloc
	jalr	t9
	beqz	v0, error
	
	# guardo el nuevo buffer
	sw	v0, LOAD_DATA_LTA_BUFFER(sp)

	# actualizo el offset
	lw	t0, LOAD_DATA_LTA_OFFSET(sp)
	addiu	t0, TAM_BUFFER
	sw	t0, LOAD_DATA_LTA_OFFSET(sp)
	
	b	loop

error:
	# libero la memoria alocada para el buffer
	lw	a0, LOAD_DATA_LTA_BUFFER(sp)
	la	t9, myfree
	jalr	t9

	#cargo el valor de retorno
	li	v0, -1
	b	unwinding_load_data

return_load_data:
	#cargo el valor de retorno
	lw	v0, LOAD_DATA_LTA_BYTES_TOTALES(sp)
	lw	t0, LOAD_DATA_LTA_BUFFER(sp)
	sw	t0, LOAD_DATA_O_ARG(sp)

unwinding_load_data:
	move	sp, $fp
	lw	ra, LOAD_DATA_O_RA(sp)
	lw	$fp, LOAD_DATA_O_FP(sp)	
	addiu	sp, sp, LOAD_DATA_SS
	jr	ra		

.end load_data	

# int main (int argc, char** argv)
#define MAIN_SS	40
#define MAIN_O_ARG (MAIN_SS)
#define MAIN_O_RA 		32
#define MAIN_O_FP 		28
#define MAIN_O_GP 		24
#define MAIN_LTA_BUFFER_SIZE	20
#define MAIN_LTA_BUFFER_PTR	16

.globl	main
.ent	main
main:
	.frame $fp, MAIN_SS, ra
	.set  noreorder
   	.cpload  t9
   	.set  reorder

	subu	sp, sp, MAIN_SS
	sw	ra, MAIN_O_RA(sp)
	sw	$fp, MAIN_O_FP(sp)
	sw	gp, MAIN_O_GP(sp)
	move	$fp, sp
	sw	a0, MAIN_O_ARG(sp)	# guardo el argumento en el ABA del caller
	sw	a1, MAIN_O_ARG+4(sp)
	
	lw	a0, MAIN_LTA_BUFFER_PTR(sp)
	la	t9, load_data	
	jalr	t9
	
	blez	v0, m_error
	sw	v0, MAIN_LTA_BUFFER_SIZE(sp)
	lw	t0, 0(sp)
	sw	t0, MAIN_LTA_BUFFER_PTR(sp)
	
	move 	a1, v0
	move 	a0, t0
	la	t9, merge_sort
	jalr	t9

	beqz	v0, msort_error
	lw	a1, 0(sp)
	lw	a2, MAIN_LTA_BUFFER_SIZE(sp)
	
	li	a0, stdoutfd
	la	t9, my_write
	jalr 	t9

	lw 	a0, MAIN_LTA_BUFFER_PTR(sp)
	la	t9, myfree
	jalr	t9
	b 	return_main

m_error:
	li	v0, -1
	b	unwinding_main

msort_error:
	lw	a0, MAIN_LTA_BUFFER_PTR(sp)
	la	t9, myfree
	jalr	t9
	li	v0, -1
	b	unwinding_main

return_main:
	li	v0, 0

unwinding_main:
	move	sp, $fp
	lw	ra, MAIN_O_RA(sp)
	lw	$fp, MAIN_O_FP(sp)	
	addiu	sp, sp, MAIN_SS
	jr	ra	
	

.end main

